import { warnEventId } from '../../../../../common/warnId';

const ruleCheckers = [
	{
		ruleId: 'respTime',
		field: 'totalTime',
		level: 1,
		abnormalChecker: ({ value, rule }) => value >= rule || value <= 0,
		titleBuilder: ({ rule }) => `服务器响应时间超过 ${rule}ms`,
	},
	{
		ruleId: 'lossRate',
		field: 'lossRate',
		level: 1,
		abnormalChecker: ({ value, rule }) => value >= rule,
		titleBuilder: ({ rule }) => `服务器丢包率超过 ${parseInt(rule * 100, 10)}%`,
	},
	{
		ruleId: 'statusCodeRange',
		field: 'statusCode',
		level: 1,
		abnormalChecker: ({ value, rule }) => {
			return rule.some(r => {
				if (Array.isArray(r)) {
					return parseInt(r[0], 10) <= value && parseInt(r[1], 10) >= value;
				}
				return parseInt(r, 10) === value;
			});
		},
		titleBuilder: ({ rule }) =>
			`服务器响应状态码异常 [${rule
				.map(r => (Array.isArray(r) ? `${r[0]}-${r[1]}` : r))
				.join(' ')}]`,
	},
];

/**
 * 根据异常规则检查扫描结果中的异常
 * @param {*} param0
 */
export default function warningCheck({ target, response, rules }) {
	const detail = response?.detail || [];
	const nodeDetailMap = detail.reduce((obj, x) => {
		obj[x.node] = { ...x, warnings: [], securityStatus: 'safe' };
		return obj;
	}, {});
	const warningMap = {};

	ruleCheckers.forEach(
		({ field, ruleId, level, abnormalChecker, titleBuilder }) => {
			const rule = rules[ruleId];
			if (!rule) return;

			const id = warnEventId({ taskType: 'http', id: ruleId, affects: target });
			const abnormalNode = new Set();
			const abnormalArea = new Set();
			detail.forEach(result => {
				const value = result[field];

				if (abnormalChecker({ value, rule, result, field })) {
					nodeDetailMap[result.node].warnings.push(id);
					nodeDetailMap[result.node].securityStatus = 'warning';
					abnormalNode.add(result.node);
					abnormalArea.add(result.area);
				}
			}, []);

			if (abnormalNode.size) {
				warningMap[id] = {
					level,
					id,
					title: titleBuilder({ rule }),
					detail: {
						node: Array.from(abnormalNode),
						area: Array.from(abnormalArea),
					},
				};
			}
		}
	);

	return {
		addition: {
			respAvg: response.respAvg,
			detail: Object.values(nodeDetailMap),
		},
		warnings: Object.values(warningMap),
	};
}
